﻿#region Copyright & License

// Copyright © 2012 - 2017 François Chabot, Yves Dierick
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#endregion

using System;
using Be.Stateless.BizTalk.ContextProperties;
using Be.Stateless.BizTalk.Unit.RuleEngine;
using Be.Stateless.Extensions;
using Microsoft.RuleEngine;
using Moq;
using NUnit.Framework;
using Assert = NUnit.Framework.Assert;

namespace Be.Stateless.BizTalk.Dsl.RuleEngine
{
	[TestFixture]
	public class StaticMemberAccessRuleFixture : PolicyFixture<StaticMemberAccessRuleFixture.StaticMemberAccessRuleSet>
	{
		[Test]
		public void ExtensionMethodResolution()
		{
			Facts
				.Assert(Context.Property(BizTalkFactoryProperties.CorrelationToken).WithValue("ExtensionMethodResolution"))
				.Assert(Context.Property(BizTalkFactoryProperties.SenderName).WithValue("0000001234567890"));

			ExecutePolicy();

			Facts.Verify(Context.Property(TrackingProperties.ProcessName).WithValue("00001234567890").HasBeenWritten());
		}

		[Test]
		public void StaticCallResolution()
		{
			Facts.Assert(Context.Property(BizTalkFactoryProperties.CorrelationToken).WithValue("StaticCallResolution"));

			ExecutePolicy();

			Facts.Verify(Context.Property(TrackingProperties.ProcessName).WithValue("HelloFromStaticCallResolution").HasBeenWritten());
		}

		[Test]
		public void StaticMemberIsCalledWheneverRuleIsFired()
		{
			// setup a callback to capture guid generated by rule
			object guid = null;
			var mock = Mock.Get(Facts.Context);
			mock
				.Setup(c => c.Promote(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>()))
				.Callback<string, string, object>((n, ns, v) => guid = v);

			using (var policyTester = new PolicyTester(RuleSet))
			{
				Facts.Assert(Context.Property(BizTalkFactoryProperties.CorrelationToken).WithValue("ActionShouldFireWheneverRuleFires"));

				policyTester.Execute(new object[] { new BizTalk.RuleEngine.Context(Facts.Context) });
				var v1 = guid;

				policyTester.Execute(new object[] { new BizTalk.RuleEngine.Context(Facts.Context) });
				var v2 = guid;

				Assert.That(v1, Is.Not.EqualTo(v2));
			}
		}

		[Test]
		public void StaticPropertyResolution()
		{
			Facts.Assert(Context.Property(BizTalkFactoryProperties.CorrelationToken).WithValue("StaticPropertyResolution"));

			ExecutePolicy();

			Facts.Verify(Context.Property(FileProperties.FileCreationTime).WithValue(DateTime.Today).HasBeenWritten());
		}

		public class StaticMemberAccessRuleSet : RuleSet
		{
			public StaticMemberAccessRuleSet()
			{
				Name = GetType().Name;

				Rules.Add(
					Rule("ExtensionMethod")
						.If(() => Context.Read(BizTalkFactoryProperties.CorrelationToken) == "ExtensionMethodResolution")
						.Then(() => Context.Write(TrackingProperties.ProcessName, Context.Read(BizTalkFactoryProperties.SenderName).SubstringEx(-14)))
					);

				Rules.Add(
					Rule("StaticCall")
						.If(() => Context.Read(BizTalkFactoryProperties.CorrelationToken) == "StaticCallResolution")
						.Then(() => Context.Write(TrackingProperties.ProcessName, string.Concat("HelloFrom", Context.Read(BizTalkFactoryProperties.CorrelationToken))))
					);

				Rules.Add(
					Rule("StaticCall.2")
						.If(() => Context.Read(BizTalkFactoryProperties.CorrelationToken) == "ActionShouldFireWheneverRuleFires")
						.Then(() => Context.Promote(BizTalkFactoryProperties.CorrelationToken, Convert.ToString(Guid.NewGuid())))
					);

				Rules.Add(
					Rule("StaticProperty")
						.If(() => Context.Read(BizTalkFactoryProperties.CorrelationToken) == "StaticPropertyResolution")
						.Then(() => Context.Write(FileProperties.FileCreationTime, DateTime.Today))
					);
			}
		}
	}
}
